<?
/*
 Copyrights MESSIN Enguerrand .Kob-Eye Tech .
 Cie EXPRESSIV France.
 */
class StorProc extends Beacon {

	var $Offset;
	var $Limit;
	var $Query;
	var $TempVar;
	var $LoopObjects;
	var $ChildObjects;
	var $NoLoop;
	var $NoPost=true;
	var $Module;
	var $GroupBy;
	// constructeur
	function StorProc() {
		$this->Data="";
		$this->Nom="Object";
		$this->MasterBeacon = "STORPROC";
		$this->NoLoop=false;
		$this->NoPost = true;
	}

	function SetFromVar($Var,$Data,$Beacon) {
		$this->Vars = $Var;
		$this->Data= $Data;
		$this->Beacon = $Beacon["BEACON"];
		if ($this->Beacon!="STORPROC") {
			$this->setChild("STORPROC");
		}
		// 		$this->init($Process);
	}

	function init($Process){
		if (!$this->Init){
			$this->Process($Process);
			//On initialisa les enfants
// 			if (sizeof($this->ChildObjects)) {
// 				for($i=0;$i<sizeof($this->ChildObjects);$i++) {
// 					if (is_object($this->ChildObjects[$i]))$this->ChildObjects[$i]->init($Process);
// 				}
// 			}
			$this->Init=true;
		}
	}

	function setVars ($Var,$Process) {
		// 		$Var = $Process->processingVars($Var);
		$this->Vars = $Var;
		$Temp=explode("|",$this->Vars);
		$this->Nom = $Process->processingVars($Temp[1]);
		$this->Query = $Process->processingVars($Temp[0]);
		if (is_string($this->Query)) $this->Query = $Process->PostProcessing($this->Query);
		/*		echo "-----------------------\r\n";
		 print_r($this->Query);*/
		if (is_array($this->Query)) {
			//Alors Il n y pas de requete a faire mais uniquement un tableau a traiter
			$this->QueryTab = $this->Query;
			$this->Query="Array";
			$this->Module="Array";
		}else{
			//Module et gestion d erreur
			$deuxPoints = explode("::",$this->Query);
			$this->Query = $deuxPoints[0];
			if (sizeof($deuxPoints)>1)for ($i=1;$i<sizeof($deuxPoints);$i++) {
				$this->Select .="m.".$deuxPoints[$i];
				if ($i<sizeof($deuxPoints)-1) $this->Select .=",";
			}
			$this->QueryTab = $deuxPoints;
			$TempData=explode("/",$this->Query);
			$this->Module=$TempData[0];
		}
		if ((strlen($Temp[2]))&&($Temp[3]!="")){
			$this->Offset = $Process->processingVars($Temp[2]);
			$this->Limit = $Process->processingVars($Temp[3]);
		}else{
			$this->Offset = 0;
			$this->Limit = SQL_MAX_LIMIT;
		}
		if (($Temp[4]!="")&&($Temp[5]!="")){
			$this->OrderType = $Process->processingVars($Temp[5]);
			$this->OrderVar = $Process->processingVars($Temp[4]);
		}/*else{
		$this->OrderType = "DESC";
		$this->OrderVar = "TmsEdit";
		}*/
		if($Temp[6]!=""){
			$this->Select.=$Process->processingVars($Temp[6]);
		}
		if($Temp[7]!=""){
			$this->GroupBy.=$Process->processingVars($Temp[7]);
		}
	}

	function ProcessLinear($Var,$Process){
		//Analyse de la requete
		$this->setVars($Var,$Process);
		if ($GLOBALS['Systeme']->isModule($this->Module)) {
			/*			echo "\r\n---------STORPROC------------\r\n";
			 print_r($this->QueryTab);*/
			//Construction/Analayse de la requete
			$TempData=explode("/",$this->Query);
			$Search="";
			for ($i=1;$i<count($TempData);$i++) {
				if ($i>1) $Search.="/";
				$Search.=$TempData[$i];
			}
			if ($Search=="") {
				if ($NoResult = $this->getChild(array($this->MasterBeacon,"LIMIT","ORDER"),"NORESULT")) {
					//Si NORESULT
					$Process=$this->processNoResult($NoResult,$Process);
				}else{
					//Pas de NORESULT donc aucun affichage
					$this->ChildObjects="";
				}
				return $Process;
			}
			//On teste si il ne s agit pas d une requete recursive
			if ($this->searchChild($this->MasterBeacon,"RECURSIV")){
				//On modifie La recherche et on ajoute L asterisque a la fin.
				//Evidement pour que ca fonctionne il doit s agir d une recherche d enfant
				//Et la donnee doit etre recursive
				$this->Recursiv = true;
				$Search.="/*";
			}
			//Execution de la requete
			$Tab=$GLOBALS['Systeme']->Modules[$this->Module]->callData($Search,"",$this->Offset,$this->Limit,$this->OrderType,$this->OrderVar,$this->Select,$this->GroupBy);
			//Si il s agit d une recherche recursive alors il faut trier et ranger les resultats pour
			//Repartir les resultats en mode recursif
			if ($this->Recursiv) {
				$Tab=$this->sortRecursivResult($Tab);
			}
			//Verifier la presence d une classe specifique
			if ((is_array($Tab))&&(sizeof($Tab)>0)&&sizeof($this->QueryTab)==1){
				//Le cas d une simple requete
				foreach ($Tab as $Key) {
					$this->Result[] = genericClass::createInstance($this->Module,$Key);
				}
				$Process=$this->parseContents($this->Result,$Process);
			}elseif(sizeof($this->QueryTab)>1){
				if (sizeof($Tab)>1&&sizeof($this->QueryTab)==2){
					foreach ($Tab as $T) {
						$gClass = genericClass::createInstance($this->Module,$T);
						$Methods = get_class_methods($gClass);
						$Meth = $this->QueryTab[1];
						if (in_array(strtolower($Meth),$Methods)){
							$this->Result[]=$gClass->$Meth();
						}else {
							$this->Result[]=$gClass->$Meth;
						}
					}
				}elseif (sizeof($Tab)&&sizeof($this->QueryTab)>2){
					foreach ($Tab as $T) {
						$this->Result[$T[$this->QueryTab[1]]]=$T[$this->QueryTab[2]];
					}
				}elseif (sizeof($Tab)){
					$gClass = genericClass::createInstance($this->Module,$Tab[0]);
					$Methods = get_class_methods($gClass);
					$Meth = $this->QueryTab[1];
					if (in_array(strtolower($Meth),$Methods)){
						// 						echo "METHODE TROUVE $Meth \r\n";
						$this->Result[]=$gClass->$Meth();
					}else{
						$this->Result[]=$gClass->$Meth;
					}
				}
				if (sizeof($this->Result)>0) {
					$Process=$this->parseContents($this->Result,$Process);
				}else {
					if ($NoResult = $this->getChild(array($this->MasterBeacon,"LIMIT","ORDER"),"NORESULT")) {
						//Si NORESULT
						$Process=$this->processNoResult($NoResult,$Process);
					}else{
						//Pas de NORESULT donc aucun affichage
						$this->ChildObjects="";
					}
				}
			}else{
				// 				echo "------------------PAS DE RESULTAT-----------------\r\n".$this->Vars."\r\n";
				//Donc pas de resultat
				if ($NoResult = $this->getChild(array($this->MasterBeacon,"LIMIT","ORDER"),"NORESULT")) {
					//Si NORESULT
					$Process=$this->processNoResult($NoResult,$Process);
				}else{
					//Pas de NORESULT donc aucun affichage
					$this->ChildObjects="";
				}

			}
		}elseif (is_string($this->Module)&&!empty($this->Module)&&$this->Module!="Array"){
			//ITERATION SUR UN ENTIER
			$Test = $this->Module;
			settype($Test,"int");
			if ($Test<$this->Module) $Test++;
			if ($Test>0) {
				//Donc on genere le tab
				for ($i=$this->Offset;$i<$Test&&$i<$this->Offset+$this->Limit;$i++) {
					$this->Result[]=$i;
				}
			}
			$Process=$this->parseContents($this->Result,$Process);
		}elseif ($this->Module=="Array"){
			//ITERATION SUR UN TABLEAU
			if (is_array($this->QueryTab)&&sizeof($this->QueryTab)) {
				$i=0;
				foreach ($this->QueryTab as $key=>$value) {
					if ($i>=$this->Offset&&$i<($this->Offset+$this->Limit)&&$i<(sizeof($this->QueryTab))) $this->Result[$key] = $value;
					$i++;
				}
				$Process=$this->parseContents($this->Result,$Process);
			}else{
				if ($NoResult = $this->getChild(array($this->MasterBeacon,"LIMIT","ORDER"),"NORESULT")) {
					//Si NORESULT
					$Process=$this->processNoResult($NoResult,$Process);
				}else{
					//Pas de NORESULT donc aucun affichage
					$this->ChildObjects="";
				}
			}
		}else{
			//			echo "\r\n----------RECHERCHE VIDE---------".$this->Vars."--\r\n";
			if ($NoResult = $this->getChild(array($this->MasterBeacon,"LIMIT","ORDER"),"NORESULT")) {
				//Si NORESULT
				$Process=$this->processNoResult($NoResult,$Process);
			}else{
				//Pas de NORESULT donc aucun affichage
				$this->ChildObjects="";
			}
		}
		return $Process;
	}

	function sortRecursivResult($Tab,$NomTab="RECURSIV_TAB") {
		//Il faut trouver la clef recursive minimale
		$Clef=-1;
		if (is_array($Tab))foreach ($Tab as $Res) {
			if ($Res["ClefReflexive"]<$Clef||$Clef==-1) $Clef=$Res["ClefReflexive"];
		}
		$Result = StorProc::sortRecursiv($Tab,$Clef,(!empty($Res["Historique"]))?$Res["Historique"]:Array(),$NomTab);
		return $Result;
	}

	function sortRecursiv($Tab,$Clef,$Histo=Array(),$NomTab="RECURSIV_TAB") {
		//On recherc dans le tableau les occurences enfantes de la clef

		if (is_array($Tab))foreach ($Tab as $Res) {
			if ($Res["ClefReflexive"]==$Clef){
				$Histo2 = $Histo;
				$Histo2[] = Array("Id"=>$Res["Id"],"ObjectType"=>$Res["ObjectType"]);
				$Res[$NomTab]= StorProc::sortRecursiv($Tab,$Res["Id"],$Histo2,$NomTab);
				$Res["Historique"] = $Histo;
				//Il faut egalement reconstituer l historique
				$Result[]=$Res;
			}
		}
		return $Result;
	}

	function processNoResult($NoResult,$Process){
		$this->ChildObjects = $NoResult->ChildObjects;
		$this->NoLoop = true;
		for ($j=0;$j<sizeof($this->ChildObjects);$j++){
			if (is_object($this->ChildObjects[$j])){
				$Process=$this->ChildObjects[$j]->Generate($Process);
			}else{
				$this->ChildObjects[$j] = $Process->processingVars($this->ChildObjects[$j]);
			}
		}
		return $Process;
	}

	function processRecursiv($Vars,$Process){
		$this->Recursiv = true;
		$this->Vars = $Process->processingVars($this->Vars);
		$this->Vars = $Process->PostProcessing($this->Vars);
		$this->Query = $Process->processVars("STORPROC-QUERY","STOR")."/".$this->Vars;
		$this->ChildObjects = $Process->processVars("STORPROC-OBJ","STOR");
		$this->PostObjects = $Process->processVars("STORPROC-POSTOBJ","STOR");
		if ($this->PostObjects=="[!STORPROC-POSTOBJ!]") $this->PostObjects="";
		$this->Nom = $Process->processVars("STORPROC-VAR","STOR");
		$this->Vars = $this->Query."|".$this->Nom;
		$Temp = $Process->processVars("STORPROC-RESULT","STOR");
		$this->setVars($this->Vars,$Process);
		if (is_array($Temp))foreach ($Temp as $Res) {
			$this->Result[] = genericClass::createInstance($this->Module,$Res);
		}
		$Process=$this->parseContents($this->Result,$Process);
		//$Process=$this->ProcessLinear($this->Vars,$Process);
		return $Process;
	}

	function loopData($Tab,$Process){
		//Generation du Data
//  		$TempChild = serialize($this->ChildObjects);
		$TempChild = $this->ChildObjects;
 		unset($this->ChildObjects);
		$k=0;
		$OldKey = $Process->TempVar["Key"];
		$OldPos = $Process->TempVar["Pos"];
		if ($Process->TempVar["Level"]>=0&&$this->Beacon!=$this->MasterBeacon){
			$Level = $Process->TempVar["Level"]+1;
		}else{
			$Level = 0;
		}

		$OldNbResult = $Process->TempVar["NbResult"];
		if (is_array($Tab))$TabKey = array_keys($Tab);
		if (sizeof($Tab)) foreach ($TabKey as $Key){
			//var_dump($TempChild);
			$Process->RegisterTempVar($this->Nom,$Tab[$Key]);
			$Process->TempVar["Key"]=$Key;
			$Process->TempVar["Pos"]=$k+1;
			$Process->TempVar["Level"]=$Level;
			// 			echo "ZOB TEST LEVEL ---> $Level \r\n";
			$Process->TempVar["NbResult"]=sizeof($Tab);
			if ($this->Recursiv){
				$Process->RegisterTempVar($this->MasterBeacon."-RESULT",$Tab[$Key]->RECURSIV_TAB);
			}
/*			$this->LoopObjects[$k] =unserialize($TempChild);
			for ($j=0,$max=sizeof($this->LoopObjects[$k]);$j<$max;$j++) {
				if (is_object($this->LoopObjects[$k][$j])){
					$Process=$this->LoopObjects[$k][$j]->Generate($Process);
				}else{
					$this->LoopObjects[$k][$j] = $Process->processingVars( $this->LoopObjects[$k][$j]);
					$this->LoopObjects[$k][$j] = $Process->PostProcessing($this->LoopObjects[$k][$j]);
				}
			}*/
			for ($j=0,$max=sizeof($TempChild);$j<$max;$j++) {
				if (is_object($TempChild[$j])){
		 			$this->LoopObjects[$k][$j] =$TempChild[$j]->__deepclone();
					$Process=$this->LoopObjects[$k][$j]->Generate($Process);
				}else{
		 			$this->LoopObjects[$k][$j] =$TempChild[$j];
					$this->LoopObjects[$k][$j] = $Process->processingVars( $this->LoopObjects[$k][$j]);
					$this->LoopObjects[$k][$j] = $Process->PostProcessing($this->LoopObjects[$k][$j]);
				}
			}
			$this->Data.=$this->getContent($this->LoopObjects[$k]);
			unset($this->LoopObjects[$k]);
			$k++;
		}
// 		$this->ChildObjects=array();
		$Process->TempVar["Level"]=0;
		$this->ChildObjects[] = $this->Data;
// 		$this->LoopObjects=Array();
		unset($this->LoopObjects);
		$Process->TempVar["Key"]=$OldKey;
		$Process->TempVar["Pos"]=$OldPos;
		$Process->TempVar["NbResult"]=$OldNbResult;
		return $Process;
	}

	//gestion des limites
	function processLimit($Vars,$Process) {
		$this->Vars = $Process->processingVars($this->Vars);
		$this->Vars = $Process->PostProcessing($this->Vars);
		$Temp = explode("|",$this->Vars);
		$Offset = $Temp[0];
		$Limit = $Temp[1];
		//Recuperation du tableau de la variable
		$Tab = $Process->processVars($this->MasterBeacon,"STOR");
		$this->Nom=$Process->processVars($this->MasterBeacon."-VAR","STOR");
		//Construction du tableau des objets concernés
		$Max = $Offset+$Limit;
		if ($Max>sizeof($Tab)) $Max=sizeof($Tab);
		$i=0;
		if (is_array($Tab))foreach ($Tab as $K=>$C){
			if ($i>=$Offset&&$i<$Max)$TabTemp[$K]=$C;
			$i++;
		}
		return $this->parseContents($TabTemp,$Process);
	}

	function processOrder($Vars,$Process) {
		$this->Vars = $Process->processingVars($this->Vars);
		$this->Vars = $Process->PostProcessing($this->Vars);
		$Vars = explode("|",$Vars);
		$Champs = $Vars[0];
		$Type = $Vars[1];
		$Tab = $Process->processVars($this->MasterBeacon,"STOR");
		$this->Nom=$Process->processVars($this->MasterBeacon."-VAR","STOR");
		$Tab=$this->bubbleSort($Tab,$Champs,$Type);
		//On ordonne la table
		//et on renvoie au parseContents
		return $this->parseContents($Tab,$Process);
	}

	function bubbleSort($tableau , $triChamp,$Type){
		$nbEnregistrement = sizeof($tableau);
		switch ($Type) {
			case "DESC":
				if (is_object($tableau[0])) $bubble=1; else $bubble = 0;
				for ($bubble; $bubble<$nbEnregistrement; $bubble++){
					for ($position = $nbEnregistrement-1; $position >0; $position--){
						if (is_object($tableau[$position])){
							$Champs = get_object_vars($tableau[$position]);
							$ChampsPrec = get_object_vars($tableau[$position-1]);
						}else{
							$Champs = $tableau[$position];
							$ChampsPrec = $tableau[$position-1];
						}
						if($Champs[$triChamp]>$ChampsPrec[$triChamp]){
							$temp = $tableau[$position];
							$tableau[$position] = $tableau[$position-1];
							$tableau[$position-1] = $temp;
						}
					}
				}
				break;
			default:
			case "ASC":
				if (is_object($tableau[0])) $bubble=1; else $bubble = 0;
				for ($bubble = 0; $bubble<$nbEnregistrement; $bubble++){
					for ($position = $nbEnregistrement-1; $position >0; $position--){
						if (is_object($tableau[$position])){
							$Champs = get_object_vars($tableau[$position]);
							$ChampsPrec = get_object_vars($tableau[$position-1]);
						}else{
							$Champs = $tableau[$position];
							$ChampsPrec = $tableau[$position-1];
						}
						if($Champs[$triChamp]<$ChampsPrec[$triChamp]){
							$temp = $tableau[$position];
							$tableau[$position] = $tableau[$position-1];
							$tableau[$position-1] = $temp;
						}
					}
				}
				break;
			case "RANDOM":
				shuffle($tableau);
				break;
		}
		return $tableau;
	}

	function Generate($Process,$Skin=false) {
		//On transforme les parametres
		//On execute le storproc
		switch ($this->Beacon) {
			CASE "RECURSIV":
				$Process=$this->processRecursiv($this->Vars,$Process);
				break;
			CASE "ORDER":
				$Process=$this->processOrder($this->Vars,$Process);
				break;
			CASE "LIMIT":
				$Process=$this->processLimit($this->Vars,$Process);
				break;
			default:
				$Process=$this->processLinear($this->Vars,$Process);
				break;
		}
		return $Process;
	}


	function parseContents($Tab,$Process){
		//On recherche l existence d enfants
		if ($this->searchChild($this->MasterBeacon,"LIMIT")||$this->searchChild($this->MasterBeacon,"ORDER")) {
			$Process->RegisterTempVar($this->MasterBeacon,$Tab);
			$Process->RegisterTempVar($this->MasterBeacon."-VAR",$this->Nom);
			$Process->TempVar["NbResult"]=sizeof($Tab);
			$this->NoLoop = true;
			for ($j=0,$max=sizeof($this->ChildObjects);$j<$max;$j++) {
				if (is_object($this->ChildObjects[$j])){
					$Process=$this->ChildObjects[$j]->Generate($Process);
				}else{
					$this->ChildObjects[$j] = $Process->processingVars($this->ChildObjects[$j]);
					$this->ChildObjects[$j] = $Process->PostProcessing($this->ChildObjects[$j]);
				}
			}
		}else{
			if (($this->searchChild($this->MasterBeacon,"RECURSIV"))&&($this->Beacon!="RECURSIV")){
				$Process->RegisterTempVar($this->MasterBeacon."-QUERY",$this->Query);
				$Process->RegisterTempVar($this->MasterBeacon."-OBJ",$this->ChildObjects);
				$Process->RegisterTempVar($this->MasterBeacon."-VAR",$this->Nom);
			}
			$Process=$this->loopData($Tab,$Process);
		}
		return $Process;
	}

	//Fonction Affichage du List Box Derniere Fonction a executer
	function Affich() {
		$Data = "";
		//Le contenu du fichier retravaill�
		if (!$this->NoLoop&&$this->Beacon!="NORESULT"){
			$Data = $this->getContent($this->ChildObjects);
		}elseif ($this->NoLoop&&$this->Beacon!="NORESULT"){
			$Data = $this->getContent($this->ChildObjects);
		}
		return $Data;
	}



}
?>